home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-09-17 | 16.9 KB | 563 lines | [TEXT/CWIE] |
- /* Sample System 7 Preferences */
-
- /* Apple Developer Technical Support */
- /* Greg Robbins */
-
- /* This application displays a sample preferences dialog
- containing edit text, radio buttons, and a file selection,
- and demonstrates storage of those items in a preferences
- file.
-
- Requires System 7, though most elements (like resource use and
- FindFolder calls) apply to System 6 also. */
-
- /* Thanks to Godfrey DiGiorgi for advice & assistance. */
-
- /* Rev 1.0 7/92 */
-
- /* Thanks to Godfrey DiGiorgi for assistance */
-
- //updates 8/96: line 166, NewModalFilterProc added; old routine names changed;
- //included <Processes.h>; Prefix.h added as prefix file for 68K and PPC MC projects
-
- #ifdef THINK_C
- #include <MacHeaders>
- #else
- #include <QuickDraw.h>
- #include <Fonts.h>
- #include <GestaltEqu.h>
- #include <Files.h>
- #include <Resources.h>
- #include <Dialogs.h>
- #include <Menus.h>
- #include <TextEdit.h>
- #include <Windows.h>
- #include <Controls.h>
- #include <Folders.h>
- #include <Errors.h>
- #include <OSUtils.h>
- #include <ToolUtils.h>
- #include <Types.h>
- #include <Memory.h>
- #include <StandardFile.h>
- #include <Aliases.h>
- #include <Processes.h>
- #endif
-
- /* preferences dialog ID and items */
-
- #define kPrefsDialogID 128
- #define kSaveButtonItem 1
- #define kCancelButtonItem 2
- #define kHighRButtonItem 3
- #define kMediumRButtonItem 4
- #define kLowRButtonItem 5
- #define kSelectButtonItem 6
- #define kSelectStatTextItem 7
- #define kEditTextItem 8
-
- /* prefs file constants */
- #define kPrefsNameStrID 128 /* name of prefs file */
- #define kPrefsCreatorType '????'
- #define kPrefsFileType 'pref'
- #define kPrefsResourceType 'Pref'
- #define kPrefsResourceID 128
- #define kFileAliasResourceID 128 /* resource ID of alias of preferred file */
-
- /* misc dialog resource IDs */
- #define kGeneralAlertID 129
- #define kIntroAlertID 130
- #define kErrorStrListID 129 /* STR saying System 7 is required */
- #define kSystem7NeededStrIndex 1
-
- #define kFinderMessageStrID -16397 /* ID of STR for default finder message */
- /* see Inside Mac VI, page 9-22 */
- #define kStrType 'STR '
-
-
- /* this structure will contain the prefs for the application */
- typedef struct {
- long prefsTypeVers; /* version number of prefs struct */
- short rButtonShort; /* radio button number */
- short fileAliasID; /* resource ID for saving alias of selected file */
- Str255 editStr; /* string from edit text box */
- } PrefsType;
-
- /* these constants may be stored in the fields of the prefs struct */
- #define kCurrentPrefsTypeVers 1
- #define kNoAliasResourceID -1
-
- /* function prototypes */
-
- void main (void);
- short OpenPrefsResFile(SignedByte prefsPerm, Boolean createFlag);
- Boolean DoPrefsDialog(PrefsType * thePrefsType, AliasHandle * fileAliasHandlePtr);
-
- void GetOrGeneratePrefs(PrefsType * thePrefsTypePtr, long versWantedLong,
- AliasHandle * fileAliasHandlePtr);
- OSErr SavePrefs(PrefsType * thePrefsTypePtr, AliasHandle * fileAliasHandlePtr);
-
- void SetPrefRadioButton(DialogPtr prefDialogPtr, short buttonItemNum,Boolean setFlag);
- void SetPrefRadioButtonTrio(DialogPtr prefDialogPtr, short item);
- void SetPrefText(DialogPtr prefDialogPtr, short textItemNum, Str255 setStr);
-
- OSErr GetPrefsName(Str255 prefName);
-
- /*
- *
- * main program
- *
- */
-
- void main ()
- {
- PrefsType currPrefs; /* prefs structure */
- AliasHandle fileAliasHandle = nil; /* "preferred" file */
-
- Boolean prefsChangedFlag;
-
- long gestAliasResponse, gestStdFileResponse, gestFSResponse;
- short tempResRefNum;
- Str255 errStr;
- OSErr retCode;
-
- /* standard toolbox initialization */
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- /* Ensure that appropriate facilities are available so I don't crash
-
- Think & MPW glue handles calls to Gestalt and FindFolder under 6.x so
- those are always available, but the Alias Manager, new Standard File,
- and FSSpecs must be present as indicated by Gestalt */
-
- retCode = Gestalt(gestaltAliasMgrAttr, &gestAliasResponse);
- if (retCode == noErr) retCode = Gestalt(gestaltFSAttr, &gestFSResponse);
- if (retCode == noErr)
- retCode = Gestalt(gestaltStandardFileAttr, &gestStdFileResponse);
-
- if (retCode != noErr ||
- (gestAliasResponse & (1 << gestaltAliasMgrPresent)) == 0 ||
- (gestFSResponse & (1 << gestaltHasFSSpecCalls)) == 0 ||
- (gestStdFileResponse & (1 << gestaltStandardFile58)) == 0) {
-
- /* display a dialog saying System 7 is needed, then bail out */
-
- GetIndString(errStr, kErrorStrListID, kSystem7NeededStrIndex);
- ParamText(errStr, nil, nil, nil);
- (void) StopAlert(kGeneralAlertID, nil);
- ExitToShell();
- }
-
- /* if there is no preference file already, display the introductory dialog */
-
- /* this is a bit lazy: it just tries to open the file, and if that succeeds,
- * the file is immediately closed
- */
-
- tempResRefNum = OpenPrefsResFile(fsRdPerm, false);
-
- if (tempResRefNum == -1)
- (void) Alert(kIntroAlertID, NewModalFilterProc( nil )); /* intro dialog */
- else CloseResFile(tempResRefNum);
-
-
- /* Three steps for the preferences dialog:
- * - get the old preference settings from the prefs file,
- * or fill in the prefs record with defaults
- * - display the dialog
- * - if the user made changes, save the new preferences
- */
-
- GetOrGeneratePrefs(&currPrefs, kCurrentPrefsTypeVers, &fileAliasHandle);
-
- prefsChangedFlag = DoPrefsDialog(&currPrefs, &fileAliasHandle);
-
- if (prefsChangedFlag) retCode = SavePrefs(&currPrefs, &fileAliasHandle);
- }
-
-
- Boolean DoPrefsDialog(PrefsType * thePrefsTypePtr, AliasHandle * fileAliasHandlePtr)
- /* display the prefs dialog; returns true if change made to prefs record */
- {
- GrafPtr savePort;
- DialogPtr prefDialogPtr;
- short item;
- Boolean doneFlag = false;
- OSErr retCode;
-
- /* keep the new preference settings only in local variables
- in case the user cancels */
-
- PrefsType newPrefsType;
- AliasHandle newFileAliasHandle;
-
- StandardFileReply mySFR;
- SFTypeList mySFTypeList;
-
- short itemType;
- Handle itemHandle;
- Rect itemRect;
-
- FSSpec tempFSSpec;
- Boolean changedFlag;
-
-
- /* the old settings are our starting point, so copy them */
- newPrefsType = *thePrefsTypePtr;
- newFileAliasHandle = *fileAliasHandlePtr;
-
- /* throw up the dialog */
- prefDialogPtr = GetNewDialog(kPrefsDialogID, nil, (WindowPtr) -1);
- if (prefDialogPtr == nil) ExitToShell(); /* hurtin’ bad */
-
- /* set up the dialog to the initial values */
- SetPrefRadioButtonTrio(prefDialogPtr, thePrefsTypePtr->rButtonShort);
- SetPrefText(prefDialogPtr, kEditTextItem, thePrefsTypePtr->editStr);
- SelectDialogItemText(prefDialogPtr, kEditTextItem, 0, 32767);
-
- /* set the initial file name by resolving the alias */
- retCode = ResolveAlias(nil, newFileAliasHandle, &tempFSSpec, &changedFlag);
- if (retCode == noErr)
- SetPrefText(prefDialogPtr, kSelectStatTextItem, tempFSSpec.name);
- else SetPrefText(prefDialogPtr, kSelectStatTextItem, "\p");
-
-
- do {
- GetPort(&savePort);
- SetPort(prefDialogPtr);
- ModalDialog(nil, &item);
- switch(item) {
-
- case kSaveButtonItem:
- /* user wants to save the current or new settings */
-
- /* copy the editText string into the new prefs record */
- GetDialogItem(prefDialogPtr, kEditTextItem,
- &itemType, &itemHandle, &itemRect);
- GetDialogItemText(itemHandle, newPrefsType.editStr);
-
- /* replace the old record with the new record */
- *thePrefsTypePtr = newPrefsType;
-
- /* if there is a new file alias, dispose of the old one and
- copy the new handle */
-
- if (*fileAliasHandlePtr != newFileAliasHandle) {
- if (*fileAliasHandlePtr != nil)
- DisposeHandle((Handle) *fileAliasHandlePtr);
- *fileAliasHandlePtr = newFileAliasHandle;
- }
- doneFlag = true;
- break;
-
- case kCancelButtonItem:
- /* abandon the new preferences structure */
- doneFlag = true;
-
- /* if an alias was allocated, dispose of it */
- if (newFileAliasHandle != *fileAliasHandlePtr &&
- newFileAliasHandle != nil)
- DisposeHandle((Handle) newFileAliasHandle);
- break;
-
- case kHighRButtonItem:
- case kMediumRButtonItem:
- case kLowRButtonItem:
- /* handle a radio button click */
- SetPrefRadioButtonTrio(prefDialogPtr, item);
- newPrefsType.rButtonShort = item;
- break;
-
- case kSelectButtonItem:
- /* select a file the usual way */
- StandardGetFile(nil, -1, mySFTypeList, &mySFR);
-
- if (mySFR.sfGood) {
-
- /* make an alias to the selected file */
-
- newPrefsType.fileAliasID = kFileAliasResourceID;
-
- /* if an alias was allocated, dispose of it */
- if (newFileAliasHandle != *fileAliasHandlePtr &&
- newFileAliasHandle != nil)
- DisposeHandle((Handle) newFileAliasHandle);
-
- retCode = NewAlias(nil, &mySFR.sfFile, &newFileAliasHandle);
-
- if (retCode != noErr) {
- /* really should display a warning or something */
- SysBeep(10);
- newFileAliasHandle = nil;
- *mySFR.sfFile.name = 0;
- newPrefsType.fileAliasID = kNoAliasResourceID;
- }
-
- /* display the selected file's name in the dialog */
-
- SetPrefText(prefDialogPtr, kSelectStatTextItem, mySFR.sfFile.name);
- }
- }
- } while (!doneFlag);
-
- DisposeDialog(prefDialogPtr);
-
- SetPort(savePort);
-
- /* if the user clicked Save, return true */
- return (item == kSaveButtonItem);
- }
-
- void SetPrefRadioButtonTrio(DialogPtr prefDialogPtr, short item)
- /* set one radio button item in the prefs dialog, clear the others */
- {
- SetPrefRadioButton(prefDialogPtr, kLowRButtonItem,(item == kLowRButtonItem));
- SetPrefRadioButton(prefDialogPtr, kMediumRButtonItem,(item == kMediumRButtonItem));
- SetPrefRadioButton(prefDialogPtr, kHighRButtonItem,(item == kHighRButtonItem));
- }
-
- void SetPrefRadioButton(DialogPtr prefDialogPtr, short buttonItemNum, Boolean setFlag)
- /* set radio button number buttonItemNum in the prefs dialog if setFlag is true */
- {
- short itemType;
- Handle itemHandle;
- Rect itemRect;
-
- GetDialogItem(prefDialogPtr, buttonItemNum, &itemType, &itemHandle, &itemRect);
- SetControlValue((ControlHandle) itemHandle, (setFlag ? 1 : 0));
- }
-
- void SetPrefText(DialogPtr prefDialogPtr, short textItemNum, Str255 setStr)
- /* set the text item in the dialog to setStr */
- {
- short itemType;
- Handle itemHandle;
- Rect itemRect;
-
- GetDialogItem(prefDialogPtr, textItemNum, &itemType, &itemHandle, &itemRect);
- SetDialogItemText(itemHandle, setStr);
- }
-
-
- void GetOrGeneratePrefs(PrefsType * thePrefsTypePtr, long wantedVers,
- AliasHandle * fileAliasHandlePtr)
- /* fill in the prefs structure from the resource file or from scratch */
- {
- short prefsResRefNum;
- Handle tempHandle;
-
- Str255 defaultStr = "\pDefault Edit Text";
-
- /* initialize prefs structure in case we can't get a valid set */
- thePrefsTypePtr->prefsTypeVers = kCurrentPrefsTypeVers;
- thePrefsTypePtr->rButtonShort = kMediumRButtonItem;
- thePrefsTypePtr->fileAliasID = kNoAliasResourceID;
- BlockMove(defaultStr, thePrefsTypePtr->editStr, *defaultStr+1);
- *fileAliasHandlePtr = nil;
-
- /* open (but don't create) the prefs file */
- prefsResRefNum = OpenPrefsResFile(fsRdPerm, false);
- if (prefsResRefNum != -1) {
-
- /* file opened successfully, get the prefs resource */
- tempHandle = Get1Resource(kPrefsResourceType, kPrefsResourceID);
-
- /* if the resource is there and it's the right size and version, copy it */
- /* (in C these can be combined with &&, but don't use AND in Pascal) */
-
- if (tempHandle != nil)
- if (GetHandleSize(tempHandle) == sizeof(PrefsType))
- if ((*(PrefsType *)*tempHandle).prefsTypeVers == wantedVers) {
-
- /* copy the prefs struct */
- *thePrefsTypePtr = *(PrefsType *)*tempHandle;
-
- /* if there's also an alias, get and detach that, too */
- if (thePrefsTypePtr->fileAliasID != kNoAliasResourceID) {
-
- /* don't orphan a previous alias handle */
- if (*fileAliasHandlePtr != nil)
- DisposeHandle((Handle) *fileAliasHandlePtr);
-
- *fileAliasHandlePtr = (AliasHandle)
- Get1Resource(rAliasType, thePrefsTypePtr->fileAliasID);
-
- if (*fileAliasHandlePtr != nil)
- DetachResource((Handle) *fileAliasHandlePtr);
- }
- }
- /* release the pref resource and close the file */
- CloseResFile(prefsResRefNum);
- }
- }
-
- OSErr SavePrefs(PrefsType * thePrefsTypePtr, AliasHandle * fileAliasHandlePtr)
- /* save the prefs structure in the prefs resource file */
- {
- OSErr retCode;
- short prefsResRefNum;
- Handle prefHandle, alisHandle, finderMessageHandle;
-
- /* open (and, if necessary, create) the prefs file */
- prefsResRefNum = OpenPrefsResFile(fsRdWrPerm, true);
- if (prefsResRefNum != -1) {
-
- /* file opened successfully, get the prefs resource */
- prefHandle = Get1Resource(kPrefsResourceType, kPrefsResourceID);
-
- if (prefHandle == nil) {
-
- /* create a new resource */
- prefHandle = NewHandle(sizeof(PrefsType));
- if (prefHandle != nil) {
-
- /* copy the prefs struct into the handle
- and make it into a resource */
-
- *(PrefsType *)*prefHandle = *thePrefsTypePtr;
- AddResource(prefHandle, kPrefsResourceType, kPrefsResourceID,
- "\pPrefsType");
- retCode = ResError();
- if (retCode != noErr) DisposeHandle(prefHandle);
- }
-
- else retCode = MemError(); /* NewHandle failed */
- }
-
- else { /* prefHandle != nil */
-
- /* update the existing resource */
- SetHandleSize(prefHandle, sizeof(PrefsType));
- retCode = MemError();
- if (retCode == noErr) {
-
- /* copy the prefs struct into the handle and tell the rsrc manager */
- *(PrefsType *)*prefHandle = *thePrefsTypePtr;
- ChangedResource(prefHandle);
- }
- }
-
- if (retCode == noErr) {
- /* now, get rid of the old fileAlias and, if the fileAliasID field
- of the prefs struct indicates that there is a new one, add it to
- the resource file */
-
- /* remove any old file alias */
- alisHandle = Get1Resource(rAliasType, thePrefsTypePtr->fileAliasID);
- if (alisHandle != nil) {
- RemoveResource(alisHandle);
- DisposeHandle(alisHandle);
- }
-
- /* if appropriate, add the current alias to the resource file */
-
- if (thePrefsTypePtr->fileAliasID != kNoAliasResourceID &&
- *fileAliasHandlePtr != nil) {
-
- AddResource((Handle) *fileAliasHandlePtr, rAliasType,
- thePrefsTypePtr->fileAliasID, "\pfile alias");
-
- /* keep the alias available */
- DetachResource((Handle) *fileAliasHandlePtr);
- }
-
- /* add the message to be displayed if the user tries
- to open the prefs file in the Finder (but don't add it
- if it's already in the preferences file) */
-
- finderMessageHandle = (Handle) GetString(kFinderMessageStrID);
- if (finderMessageHandle != nil &&
- HomeResFile((Handle) finderMessageHandle) != prefsResRefNum) {
-
- /* copy the resource into the prefs file */
- DetachResource(finderMessageHandle);
- AddResource(finderMessageHandle, kStrType, kFinderMessageStrID,
- "\pFinder message");
-
- /* if AddResource failed, dispose of the handle */
- retCode = ResError();
- if (retCode != noErr) DisposeHandle(finderMessageHandle);
- }
- }
-
- /* update and close the preference resource file,
- releasing its resources from memory */
- CloseResFile(prefsResRefNum);
- }
-
- else {
- /* couldn't open the res file */
- retCode = ResError();
- if (retCode == noErr) retCode = resFNotFound;
- }
-
- return retCode;
- }
-
- short OpenPrefsResFile(SignedByte prefsPerm, Boolean createFlag)
- /* open the preferences file with the given permission; if createFlag is set,
- create a preferences file if necessary */
- {
- OSErr retCode;
- short prefsVRefNum;
- long prefsDirID;
- Str255 prefsNameStr;
- FSSpec prefsFSSpec;
- short prefsResRefNum = -1;
-
- /* get the name of the prefs file */
- retCode = GetPrefsName(prefsNameStr);
- if (retCode == noErr) {
-
- /* Use FindFolder to locate the Preferences folder.
-
- MPW 3.2 and some other compilers provide the
- glue necessary to use FindFolder (and Gestalt) safely
- under System 6 and earlier. Under System 6, the dirID
- returned for the Preferences folder request will be
- the System folder's dirID */
-
- retCode = FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder,
- &prefsVRefNum, &prefsDirID);
- if (retCode == noErr) {
-
- /* make a file spec for the prefs file */
-
- retCode = FSMakeFSSpec(prefsVRefNum, prefsDirID, prefsNameStr,
- &prefsFSSpec);
-
- if (retCode == fnfErr && createFlag) {
- /* prefs file doesn't already exist, so create it */
- FSpCreateResFile(&prefsFSSpec, kPrefsCreatorType, kPrefsFileType,
- smSystemScript);
- retCode = ResError();
- }
-
- /* open the prefs file */
- if (retCode == noErr) {
- prefsResRefNum = FSpOpenResFile(&prefsFSSpec, prefsPerm);
- }
- }
- }
- return prefsResRefNum;
- }
-
- OSErr GetPrefsName (StringPtr prefName)
- /* get the name of the preferences file from a resource in the application */
- {
- StringHandle prefStrHandle;
- OSErr retCode = noErr;
-
- prefStrHandle = GetString(kPrefsNameStrID);
- if (prefStrHandle != nil)
- BlockMove(*prefStrHandle, prefName, (Size) (**prefStrHandle) + 1);
- else retCode = resNotFound;
-
- return retCode;
- }